package com.byron.media.server.rtsp.model;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class Sdp {

//    例子：
//    v=0
//    o=- 0 0 IN IP4 127.0.0.1  // <username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
//    s=Unnamed                 // <session name>
//    i=N/A                     // <session information>
//    c=IN IP4 192.168.10.181   // <networktype> <address type> <connection address>
//    t=0 0                     // <start time>  <stop time>
//    a=recvonly                // sendonly/recvonly/sendrecv/inactive
//    m=video 0 RTP/AVP 96      // <media> <port> <transport> <fmt list>
//    a=rtpmap:96 H264/90000    // rtpmap:<payload type><encoding name>/<clock rate>[/<encodingparameters>]
//    a=fmtp:96 packetization-mode=1;sprop-parameter-sets=Z0KAHukBQHtKQUGBgbQoTUA=,aM4G4g==;
//    a=control:trackID=1
//    m=audio 0 RTP/AVP 96
//    a=rtpmap:96 MPEG4-GENERIC/32000/2
//    a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=1290; SizeLength=13; IndexLength=3; IndexDeltaLength=3;
//    a=control:trackID=0


//    Session description
    public String v = "0";   // (protocol version)
    public String o;   // (originator and session identifier)
    public String s = "Unnamed";   // (session name)
    public String i = "N/A";   // * (session information)
    public String u;   // * (URI of description)
    public String e;   // * (email address)
    public String p;   // * (phone number)
    public String c;   // * (connection information -- not required if included in all media)
    public List<String> b = new ArrayList<>();   // * (zero or more bandwidth information lines) One or more time descriptions //("t=" and "r=" lines; see below)
    public String z;   // * (time zone adjustments)
    public String k;   // * (encryption key)
    public List<String> a = new ArrayList<>();   // * (zero or more session attribute lines) Zero or more media descriptions

//    Time description
    public String t;   // (time the session is active)
    public List<String> r = new ArrayList<>();   // * (zero or more repeat times)

    public List<MediaDescription> ms = new ArrayList<>();

//    Media description, if present
    public static class MediaDescription {
        public String m;   // (media name and transport address)
        public String i;   // * (media title)
        public String c;   // * (connection information -- optional if included at session level)
        public List<String> b = new ArrayList<>();   // * (zero or more bandwidth information lines)
        public String k;   // * (encryption key)
        public List<String> a = new ArrayList<>();   // * (zero or more media attribute lines)
    }


    public static Sdp parseSdp(String content){
        String[] lines = content.split("\r\n");
        Sdp sdp = new Sdp();
        int mediaIndex = 0;
        List<MediaDescription> ms = new ArrayList<>();
        for(String l : lines){
            if(mediaIndex == 0){
                tryToGet(sdp, l, "v");
                tryToGet(sdp, l, "o");
                tryToGet(sdp, l, "s");
                tryToGet(sdp, l, "i");
                tryToGet(sdp, l, "u");
                tryToGet(sdp, l, "e");
                tryToGet(sdp, l, "p");
                tryToGet(sdp, l, "c");
                tryToGet(sdp, l, "b");
                tryToGet(sdp, l, "z");
                tryToGet(sdp, l, "k");
                tryToGet(sdp, l, "a");
                tryToGet(sdp, l, "t");
                tryToGet(sdp, l, "r");
            } else {
                MediaDescription m = ms.get(mediaIndex - 1);
                tryToGet(m, l, "i");
                tryToGet(m, l, "c");
                tryToGet(m, l, "b");
                tryToGet(m, l, "k");
                tryToGet(m, l, "a");
            }
            if(l.startsWith("m=")){
                mediaIndex ++;
                MediaDescription m = new MediaDescription();
                m.m = l.replaceFirst("m=", "");
                ms.add(m);
            }
        }
        sdp.ms = ms;
        return sdp;
    }

    private static void tryToGet(Object sdp, String l, String key){
        String key0 = key + "=";
        if(l.startsWith(key0)){
            String value =  l.replaceFirst(key0, "");
            Field f = null;
            try {
                f = sdp.getClass().getField(key);
                if(String.class.isAssignableFrom(f.getType())){
                    f.set(sdp, value);
                } else if(List.class.isAssignableFrom(f.getType())){
                    List<String> list = (List<String>) f.get(sdp);
                    list.add(value);
                }
            } catch (NoSuchFieldException | IllegalAccessException ex) {
                ex.printStackTrace();
            }
        }
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer();
        sb.append("v=").append(v).append("\r\n");
        sb.append("o=").append(o).append("\r\n");
        sb.append("s=").append(s).append("\r\n");
        if(i != null){ sb.append("i=").append(i).append("\r\n"); }
        if(u != null){ sb.append("u=").append(u).append("\r\n"); }
        if(e != null){ sb.append("e=").append(e).append("\r\n"); }
        if(p != null){ sb.append("p=").append(p).append("\r\n"); }
        if(c != null){ sb.append("c=").append(c).append("\r\n"); }
        if(b != null && b.size() > 0){
            for(String bb : b){
                sb.append("b=").append(bb).append("\r\n");
            }
        }
        if(z != null){ sb.append("z=").append(z).append("\r\n"); }
        if(k != null){ sb.append("k=").append(k).append("\r\n"); }
        if(a != null && a.size() > 0){
            for(String aa : a){
                sb.append("a=").append(aa).append("\r\n");
            }
        }
        sb.append("t=").append(t).append("\r\n");
        if(r != null && r.size() > 0){
            for(String rr : r){
                sb.append("r=").append(rr).append("\r\n");
            }
        }
        for(MediaDescription m : ms){
            sb.append("m=").append(m.m).append("\r\n");
            if(m.i != null){ sb.append("i=").append(m.i).append("\r\n"); }
            if(m.c != null){ sb.append("c=").append(m.c).append("\r\n"); }
            if(m.b != null && m.b.size() > 0){
                for(String bb : m.b){
                    sb.append("b=").append(bb).append("\r\n");
                }
            }
            if(m.k != null){ sb.append("k=").append(m.k).append("\r\n"); }
            if(m.a != null && m.a.size() > 0){
                for(String aa : m.a){
                    sb.append("a=").append(aa).append("\r\n");
                }
            }
        }
        return sb.toString();
    }

    public static class O {
//        <username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
//        - 0 0 IN IP4 127.0.0.1
        public String username = "-";
        public String sessionId = "0";
        public String sessionVersion = "0";
        public String netType = "IN";
        public String addressType = "IP4";
        public String unicastAddress = "127.0.0.1";

        @Override
        public String toString() {
            return username + " " + sessionId + " " + sessionVersion + " " + netType + " "
                    + addressType + " " + unicastAddress;
        }
    }

    public static class Rtpmap{
//        a=rtpmap:96 H264/90000    // rtpmap:<payload type><encoding name>/<clock rate>[/<encodingparameters>]
        public String payloadType = "96";
        public String encodeName = "H264";       //
        public String clockRate = "90000";        // 时钟速率

        @Override
        public String toString() {
            return "rtpmap:" + payloadType + " " + encodeName + "/" + clockRate;
        }
    }


    public static class Fmtp {
        public String payloadType = "96";
        public String profileLevelId = "1";
        public String mode = "AAC-hbr";
        public String sizeLength = "13";
//        public String
    }



}
